package com.marathon.ershor.textrecognizer;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.os.Bundle;
import android.content.Context;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;


public class MainActivity extends Activity implements SurfaceHolder.Callback {

    private static final String TAG = "MainActivity";

    Context mContext;
    SurfaceView surface;
    SurfaceHolder mHolder;
    Camera mCamera;
    Handler mHandlerIO;
    Handler mHandlerUI;
    RecResultView mRecResultView;
    TextView mInfoView;
    Uri resultImageURI;
    boolean mPreviewStarted;
    String mJsonResult;

    public void takePicture() {
        try {
            // initCamera();
            if (mCamera == null) {
                mCamera = Camera.open();
            }

            if (mCamera != null) {
                Log.d(TAG, "start takePicture, thread:"+Thread.currentThread().getId());
                mCamera.takePicture(null, null, jpegCallback);
            }
        } catch (Exception e) {
            e.printStackTrace();
            mHandlerIO.sendEmptyMessageDelayed(1,1000);
        }
    }

    Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            mCamera.startPreview();
            Log.d(TAG,"onPictureTaken, thread id:" + Thread.currentThread().getId());
            if (data == null)
                return;

            try {
                Uri jpgUri = ImageDealer.JpegDataToUri(data);
                Bitmap bmp = ImageDealer.getRotatedImagePath(jpgUri.getPath());
                int width = bmp.getWidth();
                int height = bmp.getHeight();
                File rotatedJpeg = new File(jpgUri.getPath());

                mJsonResult = OKHttpUploader.recognizeImage(rotatedJpeg, width/2, height/2, 1);
                mJsonResult = "[{\"content\": \"e\", \"topleft\": {\"y\": 96, \"x\": 23}, \"bottomright\": {\"y\": 160, \"x\": 135}, \"label\": \"\\u6587\\u5b57\"}]";
                mRecResultView.setJson(mJsonResult);

                mHandlerIO.sendEmptyMessageDelayed(1,2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    public void createHandleThread() {
        HandlerThread handlerThread = new HandlerThread("takePicture");
        handlerThread.start();
        mHandlerIO = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                takePicture();
            }
        };

        mHandlerIO.sendEmptyMessageDelayed(1,2000);
    }

    static Boolean bHasIn = false;
    public void initCamera() {
        if (bHasIn)
            return;
        bHasIn = true;
        try {
            mHolder = surface.getHolder();
            mHolder.addCallback(MainActivity.this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        mContext = this;
        mHandlerUI = new Handler();
        mPreviewStarted = false;

        mHandlerUI.postDelayed(new Runnable() {
            public void run() {
                setContentView(R.layout.activity_main);
                surface = findViewById(R.id.camera_frame);
                mInfoView = findViewById(R.id.info_view);
                mRecResultView = findViewById(R.id.rec_result_view);
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                initCamera();
                createHandleThread();
            }
        }, 500);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        startPreview(width, height);
    }

    private void startPreview(final int width, final int height) {
        if (mPreviewStarted)
            return;

        if (mCamera == null) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    startPreview(width, height);
                }
            }, 500);
        }
        else {
            try {
                if (mCamera != null) {
                    mCamera.lock();
                    mCamera.setDisplayOrientation(90);

                    Camera.Parameters parameters = mCamera.getParameters();
                    Camera.Size cs = getSameSmallestPreviewPictureSize();
                    //Camera.Size cs = getOptimalPreviewSize(width, height);
                    parameters.setPreviewSize(cs.width, cs.height);

                    //Camera.Size cs1 = getOptimalPictureSize(width, height);
                    parameters.setPictureSize(cs.width, cs.height);
                    mCamera.setParameters(parameters);

                /*
                // 获取窗口管理器
                WindowManager wm = getWindowManager();
                Display display = wm.getDefaultDisplay();
                DisplayMetrics metrics = new DisplayMetrics();
                // 获取屏幕的宽和高
                display.getMetrics(metrics);
                int screenWidth = metrics.widthPixels;
                int screenHeight = metrics.heightPixels;
                Camera.Parameters parameters = mCamera.getParameters();
                // 设置预览照片的大小
                parameters.setPreviewSize(screenWidth, screenHeight);
                // 设置预览照片时每秒显示多少帧的最小值和最大值
                parameters.setPreviewFpsRange(4, 10);
                // 设置照片的格式
                parameters.setPictureFormat(ImageFormat.JPEG);
                // 设置JPG照片的质量
                parameters.set("jpeg-quality", 85);
                // 设置照片的大小
                parameters.setPictureSize(screenWidth, screenHeight);
                */
                    try {
                        mCamera.setPreviewDisplay(mHolder);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    mCamera.startPreview();
                    mPreviewStarted = true;
                }
            } catch (Exception e) {
            }
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopCamera();
    }

    public void stopCamera() {
        try {
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Camera.Size getSameSmallestPreviewPictureSize() {
        List<Camera.Size> sizesPicture = mCamera.getParameters().getSupportedPictureSizes();
        List<Camera.Size> sizesPreview = mCamera.getParameters().getSupportedPreviewSizes();
        Collections.reverse(sizesPicture);
        Collections.reverse(sizesPreview);
        for (Camera.Size size : sizesPicture) {
            if (sizesPreview.contains(size))
                return size;
        }
        return null;
    }


    private Camera.Size getOptimalPictureSize(int w, int h) {
        List<Camera.Size> sizes = mCamera.getParameters().getSupportedPictureSizes();
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.Size size : sizes) {
            Log.d(TAG, "picture:w"+size.width+" h:"+size.height);
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    private Camera.Size getOptimalPreviewSize(int w, int h) {
        List<Camera.Size> sizes = mCamera.getParameters().getSupportedPreviewSizes();
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) h / w;

        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        for (Camera.Size size : sizes) {
            Log.d(TAG, "preview:w"+size.width+" h:"+size.height);
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mCamera != null)
            mCamera.stopPreview();
    }

}
